﻿using DataConverter.Utils;
using QDAS;
using System.Text;

namespace DataConverter.Core
{
  public class C2021T08_Kisler : ConvertBase
    {
        /// <summary>
        /// 需要进行转换的远程数据目录。
        /// </summary>
        List<string> dataPaths = new List<string>();

        DateTime lastConvertTime = DateTime.Now;

        string listfilename = "configs/C2021T08_Kisler_pathlist.txt";

        public C2021T08_Kisler()
        {
            NeedConnectionCheck = false;
            CompanyName = "Kister 转换器";
            Version = "beta0.1.0 Released Date: 2021/12/01 Inner Name: C2021T08_Kisler";
        }

        // 保证一直转换。
        public override bool NeedConvert() => true;

        public override bool OnStart()
        {
            //if (!File.Exists(listfilename))
            //{
            //    StringBuilder sb = new StringBuilder();
            //    sb.AppendLine(@"\\192.168.3.47\shared\kistler");
            //    sb.AppendLine(@"\\192.168.1.101\kistler");
            //    File.WriteAllText(listfilename, sb.ToString());
            //}

            LoadKFields();
            ProcessDirectory(@"C:\shared\kistler\MP-009\");
            //ProcessDirectory("/home/shared/kistler/MP-009/");

            // ReadDataPaths返回所有kistler一级目录，其二级目录表示对应压机
            // 本循环用于获得指定路径的所有子目录
            foreach (var path in ReadDataPaths(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, listfilename)))
            {
                // 判断目录是否存在
                if (!Directory.Exists(path))
                    continue;

                var subdirs = Directory.GetDirectories(path);
                foreach (var subdir in subdirs)
                {
                    var dir = subdir.TrimEnd('\\').TrimEnd('/');
                    if (!dir.EndsWith("_backup") && !dir.EndsWith("_output"))
                        dataPaths.Add(dir);
                }
            }

            // lastConvertTime = ia.ReadDateTime("lastConvertTime", DateTime.Now);

            return true;
        }

        public override void OneLoop_Process()
        {
            // 对所有的目录进行遍历操作
            for (int i = 0; i < dataPaths.Count; i++)
            {
                ProcessDirectory(dataPaths[i]);
                Thread.Sleep(100);
            }
        }

        int[] exlucsives = { 6, 8, 16, 18 };

        public Dictionary<string, string[]> kfields = new Dictionary<string, string[]>();

        public void LoadKFields()
        {
            var path = Path.GetFullPath(Path.Combine(@"configs\C2021T08_kistler_kfields.csv"));
            //var path = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "configs/C2021T08_kistler_kfields.csv"));
            // 0.设备	 1.工位号	    2.工序名称   3.机器       4.机器编号    5.拧紧力矩下限	6.拧紧力矩上限   7.力矩单位   8.角度下限  9.角度上限 10.角度单位
            // 齐世乐	     DCT-0200	轴承外圈压装	DCT0200-R	110090	      10	         15             KN            201      204       mm 
            var rows = File.ReadAllLines(path, Encoding.Default);
            for (int i = 1; i < rows.Length; i++)
            {
                var cells = rows[i].Split(',');
                if (cells.Length == 11 && !kfields.ContainsKey(cells[3]))
                    kfields.Add(cells[3], cells);
            }
        }

        private void ProcessDirectory(string dataPath)
        {

            var path = dataPath.Split('|')[0];
            var pathb = path + "_backup"; // 备份文件夹
            if (!Directory.Exists(pathb))
                Directory.CreateDirectory(pathb);

            DateTime onedayago = DateTime.Today.AddDays(-1);
            foreach (var csvfilepath in Directory.GetFiles(path))
            {
                // 文件名： Part_DCT0200-L_MP-012_2021-11-12_06-52-24_A20131TJMLC0113H0_OK.csv
                // var csvfilepath1 = @"D:\shared\kistler\MP-009\Part_DCT0200-L_MP-002_2021-12-19_00-32-29_S40135C150001000B1500MM00113_OK.csv";
                var kf = KistlerFileInfo.Parse(csvfilepath);
                if (kf == null)// || kf.TestTime < onedayago)
                    continue;

                // 必需在字典中存在才会转换
                //if (!keyValuePairs.ContainsKey(kf.PartName))
                //    continue;

                // 2021/12/08 暂时不区别压机号，直接从第1位转换
                string k0010 = "UNKNOWN";
                if (kfields.ContainsKey(kf.PartName))
                    k0010 = kfields[kf.PartName][4];

                // 2021/12/30 将当前时间改为文件名中的时间作为测量时间
                DateTime testTime = kf.TestTime;

                QFile qf = new QFile();
                qf[1001] = kf.PartName;
                qf[1002] = kf.PartName;

                // 拧紧力矩
                var qcTorque = qf.AddQCharacteristic();
                qcTorque[2001] = "1";
                qcTorque[2002] = "拧紧力矩";
                if (kfields.ContainsKey(kf.PartName))
                {
                    qcTorque[2110] = kfields[kf.PartName][5];
                    qcTorque[2111] = kfields[kf.PartName][6];
                }
                qcTorque[2142] = "kN";

                // 拧紧角度
                var qcAngle = qf.AddQCharacteristic();
                qcAngle[2001] = "2";
                qcAngle[2002] = "位移";
                if (kfields.ContainsKey(kf.PartName))
                {
                    qcAngle[2110] = kfields[kf.PartName][8];
                    qcAngle[2111] = kfields[kf.PartName][9];
                }
                qcAngle[2142] = "mm";

                // 提取数据
                var lines = File.ReadAllLines(csvfilepath, Encoding.UTF8);
                var k0014 = "";
                List<string> list = new List<string>();
                for (int j = 0; j < lines.Length; j++)
                {
                    var row = lines[j];
                    // 提取K0014
                    if (k0014.Length == 0 && row.StartsWith("Part serial number;") && row.Contains(';'))
                        k0014 = row.Split(';')[1].Trim();

                    // 提取测量曲线的所有值
                    if (!lines[j].StartsWith("Measuring curve"))
                        continue;
                    j += 10;
                    while (lines[j].Length > 0 && char.IsDigit(lines[j][0]))
                    {
                        list.Add(lines[j]);
                        j++;
                    }
                }

                // 2022/01/15 加入，满足以下两点修改内容：
                // Time; X(ABSOLUTE); Y; X (ABSOLUTE)
                // 0,2184; 215,77600; -0,00384; 215,77600
                // s; mm; kN; mm
                //0,0000; 214,97540; -0,00265; 214,97540
                //0,2182; 215,77600; -0,03494; 215,77600
                StringBuilder sbTorque = new StringBuilder(); // 扭距
                StringBuilder sbAngle = new StringBuilder(); // 扭力
                //sbTorque.Append("time,kN;");
                //sbAngle.Append("time,mm;");
                var idTorque = $"08_{testTime:yyyyMMddHHmmss}_01_{list.Count:0000}_{random.NextDouble()*1000000:0}";
                var idAngle  = $"08_{testTime:yyyyMMddHHmmss}_02_{list.Count:0000}_{random.NextDouble()*1000000:0}";
                for (int i = 0; i < list.Count; i++)
                {
                    // time,mm,kN;0.0000,214.97590,0.00847;0.2184,215.77600,0.02686;0.3483,216.41750,-0.04465;
                    var row = list[i];
                    var items = row.Replace(',', '.').Split(';');

                    sbTorque.Append($"{items[0]},{items[2]};");
                    sbAngle.Append($"{items[0]},{items[1]};");

                    // 以下代码用于取最后一组值，作为终值。
                    if (i == list.Count - 1 && (qcAngle.data.Count == 0 && qcTorque.data.Count == 0))
                    {
                        var value_time = testTime.AddSeconds(double.Parse(items[0]));
                        var di1 = qcTorque.AddItem();
                        di1[0010] = k0010;
                        di1[0014] = k0014;
                        di1[0056] = idTorque;
                        di1.value = double.Parse(items[2]);
                        di1.date = value_time;

                        var di2 = qcAngle.AddItem();
                        di2[0010] = k0010;
                        di2[0014] = k0014;
                        di2[0056] = idAngle;
                        di2.value = double.Parse(items[1]);
                        di2.date = value_time;
                    }
                }

                // 输出第1条曲线数据：Torque
                File.WriteAllText(Path.Combine(OutputDirectory, idTorque + ".txt"), sbTorque.ToString());

                // 输出第2条曲线数据: Angle
                File.WriteAllText(Path.Combine(OutputDirectory, idAngle + ".txt"), sbAngle.ToString());
                SaveToDFQ(qf, OutputDirectory, $"C08_{kf.PartName}_{kf.Model}_{kf.TestTime:yyyyMMddHHmmss}_{NowString()}.dfq");
                CopyFileTo(csvfilepath, pathb, true);
            }
        }

        /// <summary>
        /// 将输入文件移动到指定的目录，文件名不变。
        /// </summary>
        /// <param name="srcfilepath">输入文件。</param>
        /// <param name="targetdir">目标文件夹。</param>
        /// <param name="deleteScr">是否删除原文件，默认值为false。</param>
        /// <param name="deleteTarget">是否删除目标文件，只有目标文件存在时才生效，默认值为true。</param>
        public void CopyFileTo(string srcfilepath, string targetdir, bool deleteScr = false, bool deleteTarget = true)
        {
            // 输出目标的文件名
            var targetFilepath = Path.Combine(targetdir, Path.GetFileName(srcfilepath));

            // 如果目标文件存在且需要删除，则删除目标文件
            if (File.Exists(targetFilepath) && deleteTarget)
                File.Delete(targetFilepath);

            // 在目标文件不存在的情况下才复制
            if (!File.Exists(targetFilepath))
                File.Copy(srcfilepath, targetFilepath);

            // deleteScr决定是否需要删除源文件
            if (deleteScr)
                File.Delete(srcfilepath);
        }

    }


    /// <summary>
    /// 用于表示CSV文件名，以从中解析出部件名，型号，测试时间等信息。
    /// CSV数据文件格式示例：Part_DCT0200-L_MP-012_2021-11-12_06-52-24_A20131TJMLC0113H0_OK.csv
    /// </summary>
    public class KistlerFileInfo
    {
        public string PartName;
        public string Model;
        public DateTime TestTime;
        public string Description;
        public string TestResult;


        public static KistlerFileInfo Parse(string path)
        {
            if (string.IsNullOrEmpty(path))
                return null;

            path = Path.GetFileNameWithoutExtension(path);

            // Part_DIFF0030_MP-009_2019-03-01_03-11-15_KB00002_OK.csv
            var strs = path.Split('_');
            if (strs.Length != 7)
                return null;

            KistlerFileInfo kfi = new KistlerFileInfo();
            try
            {
                // 0:Part, 1:DIFF0030, 2:MP-009, 3:2019-03-01, 4:03-11-15, 55:KB00002, 6:OK.csv
                kfi.PartName = strs[1];
                kfi.Model = strs[2];
                kfi.TestTime = DateTime.Parse(strs[3] + " " + strs[4].Replace('-', ':'));
                kfi.Description = strs[5];
                kfi.TestResult = strs[6].Replace(".csv", "");
            }
            catch { kfi = null; }

            return kfi;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append($"PartName: {PartName}, ");
            sb.Append($"Model: {Model}, ");
            sb.Append($"TestTime: {TestTime:yyyy/MM/dd HH:mm:ss}, ");
            sb.Append($"Description: {Description}, ");
            sb.Append($"TestResult: {TestResult}.");
            return sb.ToString();
        }


    }
}
